/*
 * Copyright 2021 KylinSoft Co., Ltd.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <QFile>
#include <QThread>
#include "config.h"
#include "error.h"

Config::Config(QObject *parent)
    : QObject(parent)
    , m_settings(new QSettings(POWER_MANAGER_CONF_PATH, QSettings::NativeFormat))
    , m_fileWatcher(new QFileSystemWatcher)
{
    if (m_settings->status() != QSettings::NoError) {
        int ret = CONFIG_QSET_INIT_ERROR;
        qCritical() << "error code: " << ret;
    }
    m_machineType = getMachineType();
    getConfData(m_machineType);
    initConnect();
}

Config::~Config() {}

int Config::machineType()
{
    return m_machineType;
}

SysData Config::getSysData()
{
    return m_sysData;
}

void Config::setBrightness(const double value)
{
    m_sysData.sysBrightness = value;
}

void Config::initConnect()
{
    m_fileWatcher->addPath(POWER_MANAGER_CONF_PATH);
    connect(m_fileWatcher, &QFileSystemWatcher::fileChanged, this, [=](QString filePath) {
        qDebug() << "file changed" << m_fileWatcher->files();
        m_fileWatcher->addPath(filePath);
        m_settings->sync();
        QStringList diffData = diffSysData();
        qDebug() << "diff data type is :" << diffData;
        emit configChanged(diffData);
    });
}

void Config::getConfData(const int &model)
{
    m_settings->sync();
    m_settings->beginGroup(CONFIG);
    m_sysData.sysPowerPolicyAc = m_settings->value(POWER_POLICY_AC).toInt();
    m_sysData.sysSleepComputerAc = m_settings->value(SLEEP_COMPUTER_AC).toInt();
    m_sysData.sysSleepDisplayAc = m_settings->value(SLEEP_DISPLAY_AC_KEY).toInt();
    if (Laptop == model) {
        m_sysData.sysPowerPolicyBat = m_settings->value(POWER_POLICY_BATTERY).toInt();
        m_sysData.sysPowerPolicyBackup = m_settings->value(POWER_POLICY_BACKUP).toInt();
        m_sysData.sysSleepComputerBat = m_settings->value(SLEEP_COMPUTER_BATTERY).toInt();
        m_sysData.sysSleepDisplayBat = m_settings->value(SLEEP_DISPLAY_BAT_KEY).toInt();
        m_sysData.sysButtonLidBat = m_settings->value(BUTTON_LID_BATTERY).toString();
        m_sysData.sysButtonLidAc = m_settings->value(BUTTON_LID_AC).toString();
        m_sysData.sysBrightness = m_settings->value(BRIGHTNESS).toInt();
        m_sysData.sysLowBattery = m_settings->value(LOW_BATTERY).toInt();
        m_sysData.sysCriticalBattery = m_settings->value(CRITICAL_BATTERY).toInt();
        m_sysData.sysActionCriticalBat = m_settings->value(ACTION_CRITICAL_BATTERY).toString();
        m_sysData.sysBatterySaver = m_settings->value(BATTERY_SAVER).toInt();
        m_sysData.sysBatterySaverPercent = m_settings->value(BATTERY_SAVER_PERCENT).toInt();
        m_sysData.sysBatterySaverAuto = m_settings->value(BATTERY_SAVER_AUTO).toBool();
        m_sysData.sysBatterySaverBrightness = m_settings->value(BATTERY_SAVER_BRIGHTNESS).toBool();
    }
    m_settings->endGroup();
    qDebug() << "init sys data";
}

QStringList Config::diffSysData()
{
    QStringList str;
    QHash<QString, QVariant> cache;
    int data1;
    QString data2;
    m_settings->beginGroup(CONFIG);
    str = m_settings->childKeys();
    for (int var = 0; var < str.size(); ++var) {
        cache.insert(str.at(var), m_settings->value(str.at(var)));
    }
    m_settings->endGroup();
    str.clear();
    str << dataJudgment(POWER_POLICY_AC, m_sysData.sysPowerPolicyAc, data1 = cache.value(POWER_POLICY_AC).toInt());
    str << dataJudgment(
        SLEEP_COMPUTER_AC, m_sysData.sysSleepComputerAc, data1 = cache.value(SLEEP_COMPUTER_AC).toInt());
    str << dataJudgment(
        SLEEP_DISPLAY_AC_KEY, m_sysData.sysSleepDisplayAc, data1 = cache.value(SLEEP_DISPLAY_AC_KEY).toInt());
    if (Laptop == m_machineType) {
        bool data3;
        str << dataJudgment(BUTTON_LID_AC, m_sysData.sysButtonLidAc, data2 = cache.value(BUTTON_LID_AC).toString());
        str << dataJudgment(BRIGHTNESS, m_sysData.sysBrightness, data1 = cache.value(BRIGHTNESS).toInt());
        str << dataJudgment(LOW_BATTERY, m_sysData.sysLowBattery, data1 = cache.value(LOW_BATTERY).toInt());
        str << dataJudgment(BATTERY_SAVER, m_sysData.sysBatterySaver, data1 = cache.value(BATTERY_SAVER).toInt());
        str << dataJudgment(
            POWER_POLICY_BATTERY, m_sysData.sysPowerPolicyBat, data1 = cache.value(POWER_POLICY_BATTERY).toInt());
        str << dataJudgment(
            POWER_POLICY_BATTERY, m_sysData.sysPowerPolicyBackup, data1 = cache.value(POWER_POLICY_BACKUP).toInt());
        str << dataJudgment(
            BUTTON_LID_BATTERY, m_sysData.sysButtonLidBat, data2 = cache.value(BUTTON_LID_BATTERY).toString());
        str << dataJudgment(
            CRITICAL_BATTERY, m_sysData.sysCriticalBattery, data1 = cache.value(CRITICAL_BATTERY).toInt());
        str << dataJudgment(
            SLEEP_DISPLAY_BAT_KEY, m_sysData.sysSleepDisplayBat, data1 = cache.value(SLEEP_DISPLAY_BAT_KEY).toInt());
        str << dataJudgment(
            SLEEP_COMPUTER_BATTERY, m_sysData.sysSleepComputerBat, data1 = cache.value(SLEEP_COMPUTER_BATTERY).toInt());
        str << dataJudgment(
            BATTERY_SAVER_AUTO, m_sysData.sysBatterySaverAuto, data3 = cache.value(BATTERY_SAVER_AUTO).toBool());
        str << dataJudgment(
            ACTION_CRITICAL_BATTERY,
            m_sysData.sysActionCriticalBat,
            data2 = cache.value(ACTION_CRITICAL_BATTERY).toString());
        str << dataJudgment(
            BATTERY_SAVER_PERCENT,
            m_sysData.sysBatterySaverPercent,
            data1 = cache.value(BATTERY_SAVER_PERCENT).toInt());
        str << dataJudgment(
            BATTERY_SAVER_BRIGHTNESS,
            m_sysData.sysBatterySaverBrightness,
            data3 = cache.value(BATTERY_SAVER_BRIGHTNESS).toBool());
    }
    str.removeAll(QString(""));
    return str;
}

int Config::getMachineType()
{
    int ret(0);
    QDBusReply<int> reply;
    m_iface = QSharedPointer<QDBusInterface>(new QDBusInterface(
        UKUI_UPOWER_SERVICE, UKUI_UPOWER_PATH, UKUI_UPOWER_INTERFACE, QDBusConnection::sessionBus()));
    while (!m_iface->isValid()) {
        qDebug() << "ukui upower will reconnection";
        QThread::sleep(1);
        m_iface = QSharedPointer<QDBusInterface>(new QDBusInterface(
            UKUI_UPOWER_SERVICE, UKUI_UPOWER_PATH, UKUI_UPOWER_INTERFACE, QDBusConnection::sessionBus()));
    }
    reply = m_iface->call("MachineType");
    if (reply.isValid()) {
        qDebug() << "MachineType is :" << reply.value();
        return reply.value();
    } else {
        ret = CONFIG_GET_MACHINE_TYPE_ERROR;
        qCritical() << "error code: " << ret;
        return -1;
    }
}

template <typename data>
QString Config::dataJudgment(const QString &type, data &D1, data &D2)
{
    if (D1 != D2) {
        D1 = D2;
        return type;
    } else {
        return "";
    }
}
